<?php

/*
 * Google sitemap
 *
 */
if ($path[0] == 'sitemap.xml') {
	$smarty->assign('sitemap', googleSitemap(array(), 0, '/'));
	header("Content-type: text/xml");
	$smarty->display("{$app_root}/admin/frontend/sitemap.tpl.xml");
	exit;
}
function googleSitemap($sitemap, $pid, $path) {
	global $db, $site;
	$pages = $db->fetchAll("SELECT p.id, r.path, r.published, r.context, r.sitemap, r.sitemap_priority, r.sitemap_changefreq FROM site_pages p LEFT JOIN site_pages_revisions r ON p.revision_id=r.id WHERE site_id=? AND parent_id=? AND active=1 ORDER BY sort", array($site['id'], $pid));
	foreach($pages as $page) {
		if ($page['sitemap']) {
			array_push($sitemap, array(
				'loc'        => 'http://' . $_SERVER['SERVER_NAME'] . str_replace('//', '/', $path . $page['path'] . "/"),
				'lastmod'    => substr($page['published'], 0, 10),
				'priority'   => $page['sitemap_priority'],
				'changefreq' => $page['sitemap_changefreq']
			));
		}
		$sitemap = googleSitemap($sitemap, $page['id'], $path . $page['path'] . '/');
	}
	return $sitemap;
}

/*
 * Robots.txt
 *
 */
if ($path[0] == 'robots.txt') {
	header("Content-type: text/plain");
	$smarty->display("{$app_root}/admin/frontend/robots.tpl.txt");
	exit;
}

/*
 * Process the path, and populate $page and $breadcrumb
 *
 */
$parent_id = 0;
$path[-1] = ''; ksort($path);
if (!$path[0]) { unset($path[0]); }
$base_path = '';
$breadcrumb = array();

if (isset($_REQUEST['revision_id'])) {
	$page_sql = "SELECT p.id, r.id AS revision_id, p.parent_id, r.title, r.path, r.link, r.meta_description, r.meta_keywords, r.template_id, r.cache_time, r.cache_time_interval, r.published, r.robots, (SELECT COUNT(*) FROM site_pages_revisions_plugins WHERE revision_id=r.id AND manage_path=1) AS plugin_manages_path FROM site_pages p LEFT JOIN site_pages_revisions r ON r.id=(SELECT MAX(id) FROM site_pages_revisions maxr WHERE maxr.page_id=p.id) WHERE p.site_id=? AND r.path=? AND p.parent_id=? AND p.id=r.page_id";
} else {
	$page_sql = "SELECT p.id, p.revision_id, p.parent_id, r.title, r.path, r.link, r.meta_description, r.meta_keywords, r.template_id, r.cache_time, r.cache_time_interval, r.published, r.robots, (SELECT COUNT(*) FROM site_pages_revisions_plugins WHERE revision_id=r.id AND manage_path=1) AS plugin_manages_path FROM site_pages p LEFT JOIN site_pages_revisions r ON p.revision_id=r.id WHERE p.site_id=? AND r.path=? AND p.parent_id=? AND active=1";
}
for($i=-1;$i<count($path)-1;$i++) {
	$this_page = $db->fetchRow($page_sql, array($site['id'], $path[$i], $parent_id));
	if (!$this_page) {
		break;
	}
	$this_page['modules'] = $db->fetchCol("SELECT module FROM site_pages_modules WHERE page_id=?", $this_page['id']);
	$this_page['full_path'] = str_replace('//', '/', $base_path . '/' . $this_page['path'] . '/');
	$parent_id = $this_page['id'];
	$breadcrumb[] = $this_page;
	if ($this_page['plugin_manages_path'] or $this_page['modules']) {
		$page_manages_path = $this_page;
	}
	$base_path = $this_page['full_path'];
}
unset($path[-1]);
$smarty->assign('breadcrumb', $breadcrumb);

if ($this_page) {
	$page = $this_page;
} elseif(isset($page_manages_path)) {
	$page = $page_manages_path;
}

if (isset($page)) {
	$page['content'] = $db->fetchPairs("SELECT name, value FROM site_pages_revisions_content WHERE revision_id=?", $page['revision_id']);
	$page['plugins'] = array_merge(
		$db->fetchAll("SELECT * FROM site_pages_revisions_plugins WHERE revision_id=?", $page['revision_id']),
		$db->fetchAll("SELECT * FROM site_templates_plugins WHERE template_id=?", $page['template_id'])
	);
	$smarty->assign('page', $page);
}

/*
 * Get the navigation.  This is a recursive array of all the pages
 *
 */
if (isset($breadcrumb[0])) {
	$module_navigation = array();
	$navigation = get_navigation($breadcrumb[0]['id'], '/', 0);
	$smarty->assign('navigation', $navigation);
	$smarty->assign('module_navigation', $module_navigation);
}
function get_navigation($parent_id, $current_path, $level) {
	global $db, $site, $breadcrumb, $path, $page, $app_root, $module_navigation;
	$pages = $db->fetchAll("SELECT p.id, GROUP_CONCAT(m.module) AS modules, r.title, r.path, r.link, r.context FROM site_pages p LEFT JOIN site_pages_modules m ON p.id=m.page_id LEFT JOIN site_pages_revisions r ON p.revision_id=r.id WHERE p.site_id=? AND p.parent_id=? AND active=1 GROUP BY p.id ORDER BY sort", array($site['id'], $parent_id));
	for($i=0;$i<count($pages);$i++) {
		$pages[$i]['full_path'] =  $current_path . $pages[$i]['path'] . '/';
		if (isset($path[$level]) and $path[$level] == $pages[$i]['path']) {
			$pages[$i]['ancestor'] = 1;
		}
		if ($page['id'] == $pages[$i]['id']) {
			$pages[$i]['active'] = 1;
		}
		$pages[$i]['children'] = get_navigation($pages[$i]['id'], $pages[$i]['full_path'], $level+1);
		if ($pages[$i]['modules']) {
			$pages[$i]['modules'] = explode(',', $pages[$i]['modules']);
			foreach($pages[$i]['modules'] as $module) {
				if (file_exists($app_root . "/admin/frontend/_modules/{$module}/navigation.php")) {
					$navigation_prefix = $current_path . $pages[$i]['path'] . '/';
					$module_navigation[$module] = include $app_root . "/admin/frontend/_modules/{$module}/navigation.php";
					$pages[$i]['children'] = array_merge($pages[$i]['children'], $module_navigation[$module]);
				}
			}
		}
	}
	
	// if we're at the top level we need to explicitly check for modules as they wouldn't otherwise be caught
	if ($parent_id == $breadcrumb[0]['id']) {
		$modules = $db->fetchCol("SELECT module FROM site_pages_modules WHERE page_id=?", $parent_id);
		foreach($modules as $module) {
			if (file_exists($app_root . "/admin/frontend/_modules/{$module}/navigation.php")) {
				$navigation_prefix = '/';
				$module_navigation[$module] = include $app_root . "/admin/frontend/_modules/{$module}/navigation.php";
				$pages = array_merge($pages, $module_navigation[$module]);
			}
		}
	}
	
	return $pages;
}

/*
 * If page has never been defined, then the home page
 * is suspended
 *
 */
if (!isset($page) and !$base_path) {
	header('HTTP/1.1 503 Service Unavailable');
	header('Retry-after: 600');
	if (file_exists($app_root . $site['home_dir'] . '/templates/maintenance.tpl.html')) {
		$smarty->display('maintenance.tpl.html');
	} else {
		echo "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n";
		echo "<html><head>\n";
		echo "<title>This site is currently undergoing maintenance.</title>\n";
		echo "</head><body>\n";
		echo "<h1>This site is currently undergoing maintenance.</h1>\n";
		echo "<p>Please retry your request later.</p>\n";
		echo "<hr>\n";
		echo "<address>".$_SERVER['SERVER_SOFTWARE']." at ".$_SERVER['SERVER_NAME']."</address>\n";
		echo "</body></html>\n";
	}
	exit;
}

/*
 * If we've got nothing in $page by now, then see if we've got any redirects, then 404
 *
 */
if (!$page) {
	$path_sans_query_string = preg_replace('/\?.*$/', '', $_SERVER['REQUEST_URI']);
	$node = $db->fetchRow("SELECT path, parent_id FROM site_pages p LEFT JOIN site_pages_revisions r ON p.revision_id=r.id WHERE redirects REGEXP '(^|[\n\r]+)" . preg_quote($path_sans_query_string) . "([\n\r]+|$)'");
	if ($node) {
		$redirect_path = '';
		if ($node['parent_id'] == 0) {
			$redirect_path = '/';
		} else {
			while($node and $node['parent_id']) {
				$redirect_path .= '/' . $node['path'];
				$node = $db->fetchRow("SELECT path, parent_id FROM site_pages p LEFT JOIN site_pages_revisions r ON p.revision_id=r.id WHERE p.id=?", $node['parent_id']);
			}
		}
		header("HTTP/1.0 301 Moved Permenantly");
		header("Location: " . $redirect_path);
		exit;
	}
	
	if ($path[0] != 'admin') {
		if (isset($_SERVER['HTTP_REFERER'])) {
			if (preg_match('/https?:\/\/' . preg_quote($site['domain_name']) . '/', $_SERVER['HTTP_REFERER'])) {
				// internal link
				$logger->err("[{$_SERVER['REMOTE_ADDR']}] Page does not exist: {$_SERVER['REQUEST_URI']}, referrer: {$_SERVER['HTTP_REFERER']} (internal link)");
			} else {
				// external link
				$logger->warn("[{$_SERVER['REMOTE_ADDR']}] Page does not exist: {$_SERVER['REQUEST_URI']}, referrer: {$_SERVER['HTTP_REFERER']} (external link)");
			}
		} else {
			// mistyped url
			$logger->info("[{$_SERVER['REMOTE_ADDR']}] Page does not exist: {$_SERVER['REQUEST_URI']} (mistyped url)");
		}
	}
	
	header("HTTP/1.0 404 Not Found");
	if (file_exists($app_root . $site['home_dir'] . '/templates/404.tpl.html')) {
		$smarty->display('404.tpl.html');
	} else {
		echo "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n";
		echo "<html><head>\n";
		echo "<title>404 Not Found</title>\n";
		echo "</head><body>\n";
		echo "<h1>Not Found</h1>\n";
		echo "<p>The requested URL " . $_SERVER['REQUEST_URI'] . " was not found on this server.</p>\n";
		echo "<hr>\n";
		echo "<address>".$_SERVER['SERVER_SOFTWARE']." at ".$_SERVER['SERVER_NAME']."</address>\n";
		echo "</body></html>\n";
	}
	exit;
}

/*
 * If $page has a link, redirect to it
 *
 */
if ($page['link']) {
	header("Location: {$page['link']}");
	exit;
}

/*
 * Assign standard smarty variables
 *
 */
$smarty->assign('title', $page['title']);
$smarty->assign('meta_description', $page['meta_description']);
$smarty->assign('meta_keywords', $page['meta_keywords']);

/*
 * Assign template variables
 *
 */
foreach($page['content'] as $key => $val) {
	$smarty->assign($key, $val);
}

/*
 * Run Plugins
 *
 */
$plugin_return = array();
$plugin_result = '';
foreach($page['plugins'] as $plugin) {
	if (file_exists($app_root . $plugin['file'])) {
		ob_start();
		$return = quarantined_include($app_root . $plugin['file'], $plugin['config'], array_slice($path, substr_count($page['full_path'], '/')-1));
		if (is_array($return)) {
			$plugin_return = array_merge($plugin_return, $return);
		}
		$plugin_result .= ob_get_contents();
		ob_end_clean();
	}
}
$smarty->assign('plugin_return', $plugin_return);
$smarty->assign('plugin_result', $plugin_result);
function quarantined_include($file, $config, $path) {
	$cwd = getcwd();
	chdir(dirname($file));
	return include $file;
	chdir($cwd);
}

/*
 * Output robots header
 *
 */
if ($page['robots']) {
	$page['robots'] = unserialize($page['robots']);
	if (is_array($page['robots'])) {
		header('X-Robots-Tag: ' . implode(', ', $page['robots']));
	}
}

/*
 * And output the template
 *
 */
if ($page['modules']) {
	// strip off the path up to the page calling the module
	if ($page['full_path'] != '/') {
		$path = array_slice($path, substr_count($page['full_path'], '/')-1);
	}
	
	$module_return = 0;
	$module_result = 0;	
	foreach($page['modules'] as $module) {
		ob_start();
		if (file_exists("{$app_root}{$site['home_dir']}/admin-custom/frontend/_modules/{$module}/{$module}.php")) {
			$module_return += require "{$app_root}{$site['home_dir']}/admin-custom/frontend/_modules/{$module}/{$module}.php";
		} elseif (file_exists("{$app_root}/admin/frontend/_modules/{$module}/{$module}.php")) {
			$module_return += require "{$app_root}/admin/frontend/_modules/{$module}/{$module}.php";
		}
		$module_result += ob_get_contents() ? 1 : 0;
		ob_end_flush();
	}
	
}

if (!$page['modules'] or (!$module_return and !$module_result)) {
	
	header('Last-modified: ' . date('r', strtotime($page['published'])));
	if ($page['cache_time'] and !isset($_REQUEST['revision_id'])) {
		header('Expires: ' . date('r', time() + ($page['cache_time'] * $page['cache_time_interval'])));
		header('Cache-control: max-age: ' . ($page['cache_time'] * $page['cache_time_interval']) . ' must-revalidate');
		header('Pragma:');
	} else {
		header('Expires: ' . date('r', time()));
		header('Cache-control: no-cache must-revalidate');
		header('Pragma: no-cache');
	}
	$template = $db->fetchRow("SELECT * FROM site_templates WHERE id=?", $page['template_id']);
	$smarty->display("site/{$template['file']}");
	
} elseif (!$module_result) {
	
	$path_sans_query_string = preg_replace('/\?.*$/', '', $_SERVER['REQUEST_URI']);
	$node = $db->fetchRow("SELECT path, parent_id FROM site_pages p LEFT JOIN site_pages_revisions r ON p.revision_id=r.id WHERE redirects REGEXP '(^|[\n\r]+)" . preg_quote($path_sans_query_string) . "([\n\r]+|$)'");
	if ($node) {
		$redirect_path = '';
		if ($node['parent_id'] == 0) {
			$redirect_path = '/';
		} else {
			while($node and $node['parent_id']) {
				$redirect_path .= '/' . $node['path'];
				$node = $db->fetchRow("SELECT path, parent_id FROM site_pages p LEFT JOIN site_pages_revisions r ON p.revision_id=r.id WHERE p.id=?", $node['parent_id']);
			}
		}
		header("HTTP/1.0 301 Moved Permenantly");
		header("Location: " . $redirect_path);
		exit;
	}
	
	if (isset($_SERVER['HTTP_REFERER'])) {
		if (preg_match('/https?:\/\/' . preg_quote($site['domain_name']) . '/', $_SERVER['HTTP_REFERER'])) {
			// internal link
			$logger->err("[{$_SERVER['REMOTE_ADDR']}] Page does not exist: {$_SERVER['REQUEST_URI']}, referrer: {$_SERVER['HTTP_REFERER']} (internal link)");
		} else {
			// external link
			$logger->warn("[{$_SERVER['REMOTE_ADDR']}] Page does not exist: {$_SERVER['REQUEST_URI']}, referrer: {$_SERVER['HTTP_REFERER']} (external link)");
		}
	} else {
		// mistyped url
		$logger->info("[{$_SERVER['REMOTE_ADDR']}] Page does not exist: {$_SERVER['REQUEST_URI']} (mistyped url)");
	}
	
	header("HTTP/1.0 404 Not Found");
	if (file_exists($app_root . $site['home_dir'] . '/templates/404.tpl.html')) {
		$smarty->display('404.tpl.html');
	} else {
		echo "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n";
		echo "<html><head>\n";
		echo "<title>404 Not Found</title>\n";
		echo "</head><body>\n";
		echo "<h1>Not Found</h1>\n";
		echo "<p>The requested URL " . $_SERVER['REQUEST_URI'] . " was not found on this server.</p>\n";
		echo "<hr>\n";
		echo "<address>".$_SERVER['SERVER_SOFTWARE']." at ".$_SERVER['SERVER_NAME']."</address>\n";
		echo "</body></html>\n";
	}
	exit;
	
}
